From 778865f316956b8ea3382168d4fe1e9d92749af1 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 28 Oct 2014 20:23:47 -0400 Subject: [PATCH] Fix toplevel input shape for csd windows We need to maintain the application-set and the the csd input shape separately, and intersect them to pass them down. --- gtk/gtkwidget.c | 90 ++++++++++++++++++++++++++++++------------ gtk/gtkwidgetprivate.h | 3 ++ gtk/gtkwindow.c | 2 +- 3 files changed, 69 insertions(+), 26 deletions(-) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index f3e4958ae9..cd7383f05e 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -943,6 +943,8 @@ static void gtk_cairo_set_event_window (cairo_t *cr, static void gtk_cairo_set_event (cairo_t *cr, GdkEventExpose *event); +static void gtk_widget_update_input_shape (GtkWidget *widget); + /* --- variables --- */ static gint GtkWidget_private_offset = 0; static gpointer gtk_widget_parent_class = NULL; @@ -5529,9 +5531,7 @@ gtk_widget_realize (GtkWidget *widget) gdk_window_shape_combine_region (priv->window, region, 0, 0); } - region = g_object_get_qdata (G_OBJECT (widget), quark_input_shape_info); - if (region) - gdk_window_input_shape_combine_region (priv->window, region, 0, 0); + gtk_widget_update_input_shape (widget); if (priv->multidevice) gdk_window_set_support_multidevice (priv->window, TRUE); @@ -12926,6 +12926,62 @@ gtk_widget_shape_combine_region (GtkWidget *widget, } } +static void +gtk_widget_update_input_shape (GtkWidget *widget) +{ + GtkWidgetPrivate *priv = widget->priv; + + /* set shape if widget has a gdk window already. + * otherwise the shape is scheduled to be set by gtk_widget_realize(). + */ + if (priv->window) + { + cairo_region_t *region; + cairo_region_t *csd_region; + cairo_region_t *app_region; + gboolean free_region; + + app_region = g_object_get_qdata (G_OBJECT (widget), quark_input_shape_info); + csd_region = g_object_get_data (G_OBJECT (widget), "csd-region"); + + free_region = FALSE; + + if (app_region && csd_region) + { + free_region = TRUE; + region = cairo_region_copy (app_region); + cairo_region_intersect (region, csd_region); + gdk_window_input_shape_combine_region (priv->window, region, 0, 0); + } + else if (app_region) + region = app_region; + else if (csd_region) + region = csd_region; + else + region = NULL; + + gdk_window_input_shape_combine_region (priv->window, region, 0, 0); + + if (free_region) + cairo_region_destroy (region); + } +} + +void +gtk_widget_set_csd_input_shape (GtkWidget *widget, + const cairo_region_t *region) +{ + GtkWidgetPrivate *priv = widget->priv; + + if (region == NULL) + g_object_set_data (G_OBJECT (widget), "csd-shade", NULL); + else + g_object_set_data_full (G_OBJECT (widget), "csd-shade", + cairo_region_copy (region), + (GDestroyNotify) cairo_region_destroy); + gtk_widget_update_input_shape (widget); +} + /** * gtk_widget_input_shape_combine_region: * @widget: a #GtkWidget @@ -12938,36 +12994,20 @@ gtk_widget_shape_combine_region (GtkWidget *widget, * Since: 3.0 **/ void -gtk_widget_input_shape_combine_region (GtkWidget *widget, +gtk_widget_input_shape_combine_region (GtkWidget *widget, cairo_region_t *region) { - GtkWidgetPrivate *priv; - g_return_if_fail (GTK_IS_WIDGET (widget)); /* set_shape doesn't work on widgets without gdk window */ g_return_if_fail (gtk_widget_get_has_window (widget)); - priv = widget->priv; - if (region == NULL) - { - if (priv->window) - gdk_window_input_shape_combine_region (priv->window, NULL, 0, 0); - - g_object_set_qdata (G_OBJECT (widget), quark_input_shape_info, NULL); - } + g_object_set_qdata (G_OBJECT (widget), quark_input_shape_info, NULL); else - { - g_object_set_qdata_full (G_OBJECT (widget), quark_input_shape_info, - cairo_region_copy (region), - (GDestroyNotify) cairo_region_destroy); - - /* set shape if widget has a gdk window already. - * otherwise the shape is scheduled to be set by gtk_widget_realize(). - */ - if (priv->window) - gdk_window_input_shape_combine_region (priv->window, region, 0, 0); - } + g_object_set_qdata_full (G_OBJECT (widget), quark_input_shape_info, + cairo_region_copy (region), + (GDestroyNotify) cairo_region_destroy); + gtk_widget_update_input_shape (widget); } diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index de4ac4a998..6eddbb45e7 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -164,6 +164,9 @@ GList * _gtk_widget_list_controllers (GtkWidget GtkPropagationPhase phase); gboolean gtk_widget_has_tick_callback (GtkWidget *widget); +void gtk_widget_set_csd_input_shape (GtkWidget *widget, + const cairo_region_t *region); + G_END_DECLS #endif /* __GTK_WIDGET_PRIVATE_H__ */ diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 6bfe836423..530b947783 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -6678,7 +6678,7 @@ shape: rect.width = gtk_widget_get_allocated_width (widget) - window_border.left - window_border.right; rect.height = gtk_widget_get_allocated_height (widget) - window_border.top - window_border.bottom; region = cairo_region_create_rectangle (&rect); - gtk_widget_input_shape_combine_region (widget, region); + gtk_widget_set_csd_input_shape (widget, region); cairo_region_destroy (region); } -- 2.30.2